package com.lagou.rpc.provider2.server;

import com.alibaba.fastjson.JSON;
import com.lagou.rpc.common.ServiceInfo;
import com.lagou.rpc.provider2.handler.RpcServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;

@Service
public class RpcServer implements DisposableBean {

    private NioEventLoopGroup boosGroup;
    private NioEventLoopGroup workerGorup;

    private CuratorFramework client;


    @Autowired
    RpcServerHandler rpcServerHandler;


    public void  start(String ip,int port){

        try {
            //1,创建线程组

            boosGroup = new NioEventLoopGroup(1);

            workerGorup = new NioEventLoopGroup();



            ServerBootstrap serverBootstrap = new ServerBootstrap();


            serverBootstrap.group(boosGroup,workerGorup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();

                            pipeline.addLast(new StringDecoder());
                            pipeline.addLast(new StringEncoder());

                            //业务处理类  TODO
                            pipeline.addLast(rpcServerHandler);
                        }
                    });

            //绑定端口

            ChannelFuture sync = serverBootstrap.bind(ip, port).sync();
            System.out.println("==================启动成功================");

            //注册服务
            register(ip,port);

            sync.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            if(boosGroup != null){
                boosGroup.shutdownGracefully();
                boosGroup = null;
            }

            if(workerGorup != null){
                workerGorup.shutdownGracefully();
                workerGorup = null;
            }
            if(client != null){
                client.close();
                client = null;
            }
        }


    }

    private void register(String ip,int port){
        //向zookeeper提交信息，创建一个临时结点，写入ip和端口内容
        //ip和端口内容已对象方式，然后JSON编码成字符串保存
        ServiceInfo serviceInfo = new ServiceInfo(ip, port);
        String data = JSON.toJSONString(serviceInfo);

        //创建zk客户端
        client = CuratorFrameworkFactory.builder()
                .connectString("127.0.0.1:2181") //server地址
                .sessionTimeoutMs(5000) // 会话超时时间
                .connectionTimeoutMs(3000) // 连接超时时间
                .retryPolicy(new ExponentialBackoffRetry(1000,5)) // 重试策略
                .namespace("tuomaxu")
                .build(); //
        client.start();
        System.out.println("Zookeeper连接成功");

        String path = "/provider/p2";
        try {
            client.create()
                    .creatingParentContainersIfNeeded()
                    .withMode(CreateMode.EPHEMERAL)
                    .forPath(path,data.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("p2注册成功");
    }

    @Override
    public void destroy() throws Exception {
        if(boosGroup != null){
            boosGroup.shutdownGracefully();
        }

        if(workerGorup != null){
            workerGorup.shutdownGracefully();
        }

        if(client != null){
            client.close();
        }
    }
}
